#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>

// Defines para configuração
#define _GNU_SOURCE
#define LIM_TOKEN 3
#define NUM_INSTRUCOES 16
#define ERRORS_LIMIT 255
#define LIM_SIMBOLOS 255
#define MEMORIA 1024
#define FALSE -1
#define TRUE -2
#define SPACE 14
#define STOP 11
#define ATRIB 15

//Estrutura de uma instrução já com uma declaração da tabela de instruções
struct instrucao {
    char nome[7];
    short int codigo;
    short int operandos;
}TabInstrucoes[NUM_INSTRUCOES];

//Estrutura de um erro já com uma declaração da tabela de erros
struct erro {
    char mensagem[255];
    int linha;
}TabErros[ERRORS_LIMIT];

//Estrutura de um label já com uma declaração da tabela de símbolos
struct simbolo {
    char simbolo[255];
    short int endereco;
}MatrizSimbolos[LIM_SIMBOLOS];

/* Estrutura de uma saída já com uma declaração do vetor de saída primário
 * Vetor temporário que armazenará os tokens tratados do arquivo. Será utilizado na segunda passagem.
 */
struct saida {
    char saida[255];
}VetSaida[MEMORIA];

// Variáveis globais
int programCounter, sybolCounter, fileLine, tokenCounter, errorCounter, numOperandos, locSTOP;
char nomeArquivo[255], caminhoArquivo[255];
short int MEM[MEMORIA];
short int REALOC[MEMORIA];

//Protótipos de funções
void armazenaErro(char * mensagem, int linha);
int buscaInstrucao(char * token);
int buscaSimbolo(char * simbolo);
int contaOcorrencia(char * texto, char caractere);
int criaArquivoBin();
void finalizaPrograma(int condicaoDeSaida);
void gravaEndereco(char * endereco);
void gravaInstrucao(int indiceInstrucao);
int gravaSimboloMatriz(char * simbolo);
void gravaSimboloSaida(char * simbolo);
void inicializaTabInstrucoes();
int isNumber(char * string);
FILE * openFile();
char * removeChar(char * texto, char caractere);
void segundaPassagem();
char * strToUpper(char * str);
char * trataLinha(char * linha);
void trataCaminhoArquivo(char * caminhoArq);